home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 August: Tool Chest / Dev.CD Aug 00 TC Disk 1.toast / pc / sample code / contributed / waste / waste 1.3 / source / wefonttables.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-06-23  |  8.6 KB  |  343 lines

  1. /*
  2.  *    WEFontTables.c
  3.  *
  4.  *    WASTE PROJECT
  5.  *  Font Mapping Tables
  6.  *
  7.  *  Copyright (c) 1993-1998 Marco Piovanelli
  8.  *    All Rights Reserved
  9.  *
  10.  *  C port by Dan Crevier
  11.  *
  12.  */
  13.  
  14.  
  15. #include "WASTEIntf.h"
  16.  
  17. enum
  18. {
  19.     weFontTableSignature            =    'FISH',
  20.     weCurrentFontTableVersion        =    0x01008000        //    1.0
  21. };
  22.  
  23. typedef struct
  24. {
  25.     FourCharCode ftSignature;    //    must be weFontTableSignature
  26.     UInt32 ftVersion;            //    font table version, in NumVersion format
  27.     UInt32 ftNumEntries;        //    entry count
  28.     UInt32 ftReserved;            //    reserved for future use
  29. } WEFontTableHeader, *WEFontTableHeaderPtr;
  30.  
  31. typedef struct
  32. {
  33.     SInt16 ftOldFontID;        //    font ID on save
  34.     SInt16 ftNewFontID;        //    font ID on re-open
  35.     SInt32 ftEncoding;        //    character encoding (currently = script code)
  36.     SInt32 ftReserved;        //    reserved for future use
  37.     UInt32 ftNameOffset;    //    offset to font name
  38. } WEFontTableEntry, *WEFontTableEntryPtr;
  39.  
  40. typedef struct
  41. {
  42.     WEFontTableHeader ftHeader;
  43.     WEFontTableEntry ftEntries [ kVariableLengthArray ];
  44.     //    packed font names follow
  45. } WEFontTable, *WEFontTablePtr, **WEFontTableHandle;
  46.  
  47. pascal OSErr WEBuildFontTable(Handle hFontTable, WEFontIDToNameUPP fontIDToNameProc, WEHandle hWE)
  48. {
  49.     Handle hStyles = nil;
  50.     WEStyleTableEntry *pStyle, *pStyle2;
  51.     WEFontTablePtr pFontTable;
  52.     SInt32 nStyles, styleIndex, styleIndex2;
  53.     WEFontTableEntry entry;
  54.     WEFontTableEntryPtr pEntry;
  55.     Str255 fontName;
  56.     SInt32 fontCount;
  57.     SInt32 fontNameOffset;
  58.     Size fontNameSize, offsetAdjustment;
  59.     Boolean saveStylesLock;
  60.     OSErr err;
  61.  
  62.     //    return an error code is hFontTable is nil
  63.     err = nilHandleErr;
  64.     if (hFontTable == nil)
  65.     {
  66.         goto cleanup;
  67.     }
  68.  
  69.     //    clone the style table, as we need a modifiable copy
  70.     hStyles = (Handle) (*hWE)->hStyles;
  71.     if ((err = HandToHand(&hStyles)) != noErr)
  72.     {
  73.         hStyles = nil;
  74.         goto cleanup;
  75.     }
  76.  
  77.     //    lock the style table
  78.     saveStylesLock = _WESetHandleLock(hStyles, true);
  79.  
  80.     //    fill in font table header
  81.     SetHandleSize(hFontTable, sizeof(WEFontTableHeader));
  82.     if ((err = MemError()) != noErr)
  83.     {
  84.         goto cleanup;
  85.     }
  86.     pFontTable = * (WEFontTableHandle) hFontTable;
  87.     _WEBlockClr(pFontTable, sizeof(WEFontTableHeader));
  88.     pFontTable->ftHeader.ftSignature = weFontTableSignature;
  89.     pFontTable->ftHeader.ftVersion = weCurrentFontTableVersion;
  90.  
  91.     //    init counters
  92.     fontCount = 0;
  93.     fontNameOffset = sizeof(WEFontTableHeader);
  94.  
  95.     //    walk the style table
  96.     nStyles = (*hWE)->nStyles;
  97.     for (    styleIndex = 0,
  98.             pStyle = (WEStyleTableEntry *) *hStyles;
  99.             styleIndex < nStyles;
  100.             styleIndex++, pStyle++ )
  101.     {
  102.         //    skip this style table entry if it's either unused
  103.         //    or it references a font we have already processed
  104.         if (pStyle->refCount == 0)
  105.         {
  106.             continue;
  107.         }
  108.  
  109.         //    get the name of this font
  110.         BLOCK_CLR(fontName);
  111.         GetFontName(pStyle->info.runStyle.tsFont, fontName);
  112.  
  113.         //    caller can customize the building process by supplying
  114.         //    a mapping function
  115.         if (fontIDToNameProc != nil)
  116.         {
  117.             if ((err = CallWEFontIDToNameProc(pStyle->info.runStyle.tsFont, fontName, fontIDToNameProc)) != noErr)
  118.             {
  119.                 goto cleanup;
  120.             }
  121.         }
  122.  
  123.         //    calculate the space needed by the font name
  124.         //    for optimal alignment, make sure it's a multiple of 4
  125.         fontNameSize = StrLength(fontName) + 4;
  126.         fontNameSize &= ~3;
  127.  
  128.         //    append font name at the end of the font table
  129.         if ((err = _WESplice(hFontTable, fontName, fontNameSize, -1)) != noErr)
  130.         {
  131.             goto cleanup;
  132.         }
  133.  
  134.         //    create a new font table entry for this font
  135.         BLOCK_CLR(entry);
  136.         entry.ftNewFontID = entry.ftOldFontID = pStyle->info.runStyle.tsFont;
  137.         entry.ftEncoding = FontToScript(entry.ftOldFontID);
  138.         entry.ftNameOffset = fontNameOffset;
  139.         fontNameOffset += fontNameSize;
  140.  
  141.         //    add a new entry to the font table
  142.         pFontTable = * (WEFontTableHandle) hFontTable;
  143.         if ((err = _WESplice(hFontTable, &entry, sizeof(entry),
  144.                 sizeof(WEFontTableHeader) + sizeof(WEFontTableEntry) * fontCount)) != noErr)
  145.         {
  146.             goto cleanup;
  147.         }
  148.         fontCount++;
  149.  
  150.         //    mark all remaining entries in the style table which reference
  151.         //    the font ID we have just processed, so that we'll skip them
  152.         for (     styleIndex2 = styleIndex + 1, pStyle2 = pStyle + 1;
  153.                 styleIndex2 < nStyles;
  154.                 styleIndex2++, pStyle2++ )
  155.         {
  156.             if (pStyle2->info.runStyle.tsFont == entry.ftOldFontID)
  157.             {
  158.                 pStyle2->refCount = 0;
  159.             }
  160.         }
  161.     }    // for
  162.  
  163.     //    save font count in font table header
  164.     pFontTable = * (WEFontTableHandle) hFontTable;
  165.     pFontTable->ftHeader.ftNumEntries = fontCount;
  166.  
  167.     //    adjust name offsets in the font table
  168.     offsetAdjustment = sizeof(WEFontTableEntry) * fontCount;
  169.     for (    pEntry = &pFontTable->ftEntries[0];
  170.             fontCount > 0;
  171.             fontCount--, pEntry++ )
  172.     {
  173.         pEntry->ftNameOffset += offsetAdjustment;
  174.     }
  175.  
  176.     //    clear result code
  177.     err = noErr;
  178.  
  179. cleanup:
  180.     _WEForgetHandle(&hStyles);
  181.  
  182.     //    return result code
  183.     return err;
  184. }
  185.  
  186. pascal OSErr WEUpdateFontTable(Handle hFontTable, WEFontNameToIDUPP fontNameToIDProc, Boolean *wasChanged)
  187. {
  188.     WEFontTablePtr pFontTable;
  189.     WEFontTableEntryPtr pEntry;
  190.     ConstStr255Param fontName;
  191.     Size fontTableSize;
  192.     SInt32 fontCount;
  193.     Str255 systemFontName;
  194.     Boolean saveFontTableLock = false;
  195.     Boolean changed = false;    //    assume font table won't change
  196.     OSErr err;
  197.  
  198.     //    return an error code is hFontTable is nil
  199.     err = nilHandleErr;
  200.     if (hFontTable == nil)
  201.     {
  202.         goto cleanup;
  203.     }
  204.  
  205.     //    lock the font table
  206.     saveFontTableLock = _WESetHandleLock(hFontTable, true);
  207.     pFontTable = * (WEFontTableHandle) hFontTable;
  208.  
  209.     //    make sure the font table is a reasonable size
  210.     fontTableSize = GetHandleSize(hFontTable);
  211.     err = weCorruptDataErr;
  212.     if (fontTableSize < sizeof(WEFontTableHeader))
  213.     {
  214.         goto cleanup;
  215.     }
  216.  
  217.     //    check font table signature
  218.     if (pFontTable->ftHeader.ftSignature != weFontTableSignature)
  219.     {
  220.         goto cleanup;
  221.     }
  222.  
  223.     //    check font table version
  224.     //    assume we know how to handle all 1.x versions
  225.     //    if a new, incompatible format is designed in the future, it will
  226.     //    have to bump the version number to 2.x so this code can safely skip it
  227.     err = weNewerVersionErr;
  228.     if ((pFontTable->ftHeader.ftVersion & 0xFF000000) != 0x01000000)
  229.     {
  230.         goto cleanup;
  231.     }
  232.  
  233.     //    check entry count
  234.     err = weCorruptDataErr;
  235.     if (fontTableSize < sizeof(WEFontTableHeader) + sizeof(WEFontTableEntry) * pFontTable->ftHeader.ftNumEntries)
  236.     {
  237.         goto cleanup;
  238.     }
  239.  
  240.     //    get name of system font
  241.     GetFontName(systemFont, systemFontName);
  242.  
  243.     //    walk the font table
  244.     for (    fontCount = pFontTable->ftHeader.ftNumEntries,
  245.             pEntry = &pFontTable->ftEntries[0];
  246.             fontCount > 0 ;
  247.             fontCount--, pEntry++ )
  248.     {
  249.         //    calculate pointer to font name
  250.         fontName = (ConstStr255Param) (((UInt32) pFontTable) + pEntry->ftNameOffset);
  251.  
  252.         //    by default, map font name to font ID using GetFNum()
  253.         GetFNum(fontName, &pEntry->ftNewFontID);
  254.  
  255.         //    GetFNum() returns zero either because the specified font
  256.         //    is the system font, or because it doesn't exist
  257.         if ((pEntry->ftNewFontID == 0) && !EqualString(fontName, systemFontName, false, false))
  258.         {
  259.             //    missing font:
  260.             //    use a replacement font with the same character encoding, if possible
  261.             pEntry->ftNewFontID = GetScriptVariable(GetScriptVariable(pEntry->ftEncoding,
  262.                         smEnabled) ? pEntry->ftEncoding : smSystemScript, smScriptAppFond);
  263.         }
  264.  
  265.         //    caller can customize the name resolution process
  266.         //    by specifying a mapping function
  267.         if (fontNameToIDProc != nil)
  268.         {
  269.             //    map font name to font ID using the supplied mapping function
  270.             if ((err = CallWEFontNameToIDProc(fontName, pEntry->ftOldFontID, &pEntry->ftNewFontID, fontNameToIDProc)) != noErr)
  271.             {
  272.                 goto cleanup;
  273.             }
  274.         }
  275.  
  276.         if (pEntry->ftOldFontID != pEntry->ftNewFontID)
  277.         {
  278.             changed = true;
  279.         }
  280.     }    //    for
  281.  
  282.     //    clear result code
  283.     err = noErr;
  284.  
  285. cleanup:
  286.     //    unlock the font table
  287.     if (hFontTable != nil)
  288.     {
  289.         _WESetHandleLock(hFontTable, saveFontTableLock);
  290.     }
  291.  
  292.     //    return wasChanged flag
  293.     if (wasChanged != nil)
  294.     {
  295.         *wasChanged = changed;
  296.     }
  297.  
  298.     //    return result code
  299.     return err;
  300. }
  301.  
  302. pascal OSErr WEUpdateStyleScrap(StScrpHandle hStyles, Handle hFontTable)
  303. {
  304.     WEFontTablePtr pFontTable;
  305.     WEFontTableEntryPtr pEntry;
  306.     ScrpSTElement *pStyle;
  307.     SInt32 fontCount, styleCount;
  308.     SInt16 oldFontID, newFontID;
  309.  
  310.     //    this function doesn't move memory, so we can
  311.     //    safely dereference hFontTable without locking it
  312.     pFontTable = * (WEFontTableHandle) hFontTable;
  313.  
  314.     //    remap font IDs in the style table associated with the specified WE instance
  315.     for (    fontCount = pFontTable->ftHeader.ftNumEntries,
  316.             pEntry = &pFontTable->ftEntries[0];
  317.             fontCount > 0 ;
  318.             fontCount--, pEntry++ )
  319.     {
  320.         oldFontID = pEntry->ftOldFontID;
  321.         newFontID = pEntry->ftNewFontID;
  322.  
  323.         //    skip inner loop if there's nothing to change
  324.         if (oldFontID == newFontID)
  325.         {
  326.             continue;
  327.         }
  328.  
  329.         for (    styleCount = (*hStyles)->scrpNStyles,
  330.                 pStyle = & (*hStyles)->scrpStyleTab[0];
  331.                 styleCount > 0;
  332.                 styleCount--, pStyle++ )
  333.         {
  334.             if (pStyle->scrpFont == oldFontID)
  335.             {
  336.                 pStyle->scrpFont = newFontID;
  337.             }
  338.         }    //    for
  339.     }    //    for
  340.  
  341.     return noErr;
  342. }
  343.